package com.telecom.util;

import org.apache.commons.beanutils.BeanUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.*;

//@SuppressWarnings("unchecked")
public class EntityFactory2 {
    private static final Map<String, Object> BEAN_CACHE=new HashMap<>();
    private static final String CONFIG_FILE="bean.xml";
    public static <T> Optional<T> getBean(Class<T> tClass){
        String className=tClass.getName();
        T t = (T) BEAN_CACHE.get(className);
        if (!Objects.isNull(t)){
            return Optional.of(t);
        }
        try{
            Document document=parseXml();
            if (document==null){
                throw new RuntimeException("文件对象加载失败");
            }
            Element root=document.getRootElement();
            List<Element> elements=root.elements("bean");
            for (Element element: elements) {
                String clazzName = element.attributeValue("class");
                if (clazzName.equals(className)){
                    T t1=createBean(tClass,element);
                    BEAN_CACHE.put(className,t1);
                    return Optional.of(t1);
                }
            }
        }catch (Exception e){
            throw new RuntimeException("创建对象失败:"+e);
        }
        return Optional.empty();
    }
    //解析xml文件单独放在一个方法中
    private static Document parseXml() throws DocumentException {
        SAXReader reader=new SAXReader();
        InputStream inputStream=EntityFactory2.class.getClassLoader().getResourceAsStream(CONFIG_FILE);
        if (inputStream==null){
            throw new RuntimeException("配置文件读取异常");
        }
        return reader.read(inputStream);
    }
    //封装创建对象的方法
    private static <T> T createBean(Class<T> tClass, Element element) throws Exception{
        Constructor<T> constructor = tClass.getDeclaredConstructor();
        constructor.setAccessible(true);
        T t = constructor.newInstance();
        List<Element> properties = element.elements("property");
        for (Element property : properties) {
            String name = property.attributeValue("name");//name
            String value = property.attributeValue("value");//张三
            Field field = tClass.getDeclaredField(name);
            field.setAccessible(true);//设置私有属性可访问
            BeanUtils.setProperty(t, name, value);
        }
        return t;
    }
}
